﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace zuJianClient.PacketDto
{
    /// <summary>
    /// 通讯数据主包格式定义,发送和接收为同样的格式
    /// 所有数字类型都为低位在前
    /// </summary>
    public class MainPacket
    {
        /// <summary>
        /// 开始标记,长度1字节,固定为0x01
        /// </summary>
        public byte Header { get; set; } = 0x01;
        /// <summary>
        /// 数据包内容Content字段长度,占用4字节,低位在前,是字节的总和
        /// </summary>
        public uint Length { get; set; }
        /// <summary>
        /// 分包顺序索引,占用4字节,低位在前
        /// </summary>
        public uint PartIndex { get; set; } = 0x00;
        /// <summary>
        /// 分包总数,占用4字节,低位在前
        /// </summary>
        public uint PartCount { get; set; } = 0x00;
        /// <summary>
        /// 版本号,占用1字节,固定为0x01
        /// </summary>
        public byte Version { get; set; } = 0x01;
        /// <summary>
        /// 命令号,占用2字节,低位在前
        /// </summary>
        public ushort Command { get; set; }
        /// <summary>
        /// 会话ID,占用16字节
        /// </summary>
        public byte[] SessionID { get; set; } = new byte[16];
        /// <summary>
        /// 数据包内容,可变长度
        /// </summary>
        public byte[] Content { get; set; }
        /// <summary>
        /// 校验和,占用1字节
        /// </summary>
        public byte Flag { get; set; } = 0x00;
        /// <summary>
        /// 结束标记,长度1字节,固定为0x01
        /// </summary>
        public byte Tail { get; set; } = 0x01;

        /// <summary>
        ///  数据包构造函数,需要指定Content字段长度
        /// </summary>
        /// <param name="contentLength"></param>
        /// <param name="command"></param>
        /// <param name="content"></param>
        public MainPacket(int command,string content)
        {
            Length = (uint)content.Length/2;
            Command = (ushort)command;
            Content = StringToByteArray(content);
            SessionID = Guid.NewGuid().ToByteArray();
        }

        /// <summary>
        /// 对象转换为字节数组
        /// </summary>
        /// <param name="hex"></param>
        /// <returns></returns>
        public byte[] ToByteArray()
        {
          return  Convert.FromHexString(ToHexString());
        }

        /// <summary>
        /// 将对象转换为十六进制字符串
        /// </summary>
        /// <returns></returns>
        public string ToHexString()
        {
            var sb = new StringBuilder();
            sb.Append(Header.ToString("X2").ToLower());  
            sb.Append(HightLowConver((int)Length, "X8")); 
            sb.Append(PartIndex.ToString("X8"));
            sb.Append(PartCount.ToString("X8"));
            sb.Append(Version.ToString("X2"));
            sb.Append(HightLowConver((int)Command, "X4"));
            sb.Append(BitConverter.ToString(SessionID).Replace("-", ""));
            if (Content != null)
               sb.Append(BitConverter.ToString(Content).Replace("-", ""));
            sb.Append(Flag.ToString("X2"));
            sb.Append(Tail.ToString("X2"));
            return sb.ToString();
        }

        /// <summary>
        /// 从十六进制字符串解析对象
        /// </summary>
        /// <param name="hexString"></param>
        /// <returns></returns>
        public MainPacket(string hexString)
        {
            Header = Convert.ToByte(hexString.Substring(0, 2), 16);
            Length = (uint)HightLowConver(hexString.Substring(2, 8));
            PartIndex = Convert.ToUInt32(hexString.Substring(10, 8), 16);
            PartCount = Convert.ToUInt32(hexString.Substring(18, 8), 16);
            Version = Convert.ToByte(hexString.Substring(26, 2), 16);
            Command = (ushort)HightLowConver(hexString.Substring(28, 4));
            string sessionIdHex = hexString.Substring(32, 32);
            SessionID = new byte[16];
            for (int i = 0; i < sessionIdHex.Length; i += 2)
            {
                SessionID[i / 2] = Convert.ToByte(sessionIdHex.Substring(i, 2), 16);
            }
            // 可选字段Content
            if (Length > 0)
            {
                Console.WriteLine("长度:"+Length.ToString());
                string contentHex = hexString.Substring(64, (int)Length * 2);
                Content = new byte[contentHex.Length / 2];
                for (int i = 0; i < contentHex.Length; i += 2)
                {
                    Content[i / 2] = Convert.ToByte(contentHex.Substring(i, 2), 16);
                }
            }else
            {
                Content = Array.Empty<byte>();
            }
            Flag = Convert.ToByte(hexString.Substring(hexString.Length - 4, 2), 16);
            Tail = Convert.ToByte(hexString.Substring(hexString.Length - 2, 2), 16);
        }
    }
}
